home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / WarpQuake / Src / d_surf.c < prev    next >
C/C++ Source or Header  |  2000-05-22  |  7KB  |  337 lines

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // d_surf.c: rasterization driver surface heap manager
  21.  
  22. #include "quakedef.h"
  23. #include "d_local.h"
  24. #include "r_local.h"
  25.  
  26. qboolean        r_cache_thrash;         // set if surface cache is thrashing
  27.  
  28. static int                    sc_size;
  29. surfcache_t                 *sc_rover;
  30. static surfcache_t    *sc_base;
  31.  
  32. #define GUARDSIZE       4
  33.  
  34.  
  35. int     D_SurfaceCacheForRes (int width, int height)
  36. {
  37.     int             size, pix;
  38.  
  39.     if (COM_CheckParm ("-surfcachesize"))
  40.     {
  41.         size = Q_atoi(com_argv[COM_CheckParm("-surfcachesize")+1]) * 1024;
  42.         return size;
  43.     }
  44.     
  45.     size = SURFCACHE_SIZE_AT_320X200;
  46.  
  47.     pix = width*height;
  48.     if (pix > 64000)
  49.         size += (pix-64000)*3;
  50.         
  51.  
  52.     return size;
  53. }
  54.  
  55. void D_CheckCacheGuard (void)
  56. {
  57.     byte    *s;
  58.     int             i;
  59.  
  60.     s = (byte *)sc_base + sc_size;
  61.     for (i=0 ; i<GUARDSIZE ; i++)
  62.         if (s[i] != (byte)i)
  63.             Sys_Error ("D_CheckCacheGuard: failed");
  64. }
  65.  
  66. void D_ClearCacheGuard (void)
  67. {
  68.     byte    *s;
  69.     int             i;
  70.     
  71.     s = (byte *)sc_base + sc_size;
  72.     for (i=0 ; i<GUARDSIZE ; i++)
  73.         s[i] = (byte)i;
  74. }
  75.  
  76.  
  77. /*
  78. ================
  79. D_InitCaches
  80.  
  81. ================
  82. */
  83. void D_InitCaches (void *buffer, int size)
  84. {
  85.  
  86.     if (!msg_suppress_1)
  87.         Con_Printf ("%ik surface cache\n", size/1024);
  88.  
  89.     sc_size = size - GUARDSIZE;
  90.     sc_base = (surfcache_t *)buffer;
  91.     sc_rover = sc_base;
  92.     
  93.     sc_base->next = NULL;
  94.     sc_base->owner = NULL;
  95.     sc_base->size = sc_size;
  96.     
  97.     D_ClearCacheGuard ();
  98. }
  99.  
  100.  
  101. /*
  102. ==================
  103. D_FlushCaches
  104. ==================
  105. */
  106. void D_FlushCaches (void)
  107. {
  108.     surfcache_t     *c;
  109.     
  110.     if (!sc_base)
  111.         return;
  112.  
  113.     for (c = sc_base ; c ; c = c->next)
  114.     {
  115.         if (c->owner)
  116.             *c->owner = NULL;
  117.     }
  118.     
  119.     sc_rover = sc_base;
  120.     sc_base->next = NULL;
  121.     sc_base->owner = NULL;
  122.     sc_base->size = sc_size;
  123. }
  124.  
  125. /*
  126. =================
  127. D_SCAlloc
  128. =================
  129. */
  130. surfcache_t     *D_SCAlloc (int width, int size)
  131. {
  132.     surfcache_t             *new;
  133.     qboolean                wrapped_this_time;
  134.  
  135.     if ((width < 0) || (width > 256))
  136.         Sys_Error ("D_SCAlloc: bad cache width %d\n", width);
  137.  
  138.     if ((size <= 0) || (size > 0x10000))
  139.         Sys_Error ("D_SCAlloc: bad cache size %d\n", size);
  140.     
  141.     size = (int)&((surfcache_t *)0)->data[size];
  142.     size = (size + 3) & ~3;
  143.     if (size > sc_size)
  144.         Sys_Error ("D_SCAlloc: %i > cache size",size);
  145.  
  146. // if there is not size bytes after the rover, reset to the start
  147.     wrapped_this_time = false;
  148.  
  149.     if ( !sc_rover || (byte *)sc_rover - (byte *)sc_base > sc_size - size)
  150.     {
  151.         if (sc_rover)
  152.         {
  153.             wrapped_this_time = true;
  154.         }
  155.         sc_rover = sc_base;
  156.     }
  157.         
  158. // colect and free surfcache_t blocks until the rover block is large enough
  159.     new = sc_rover;
  160.     if (sc_rover->owner)
  161.         *sc_rover->owner = NULL;
  162.     
  163.     while (new->size < size)
  164.     {
  165.     // free another
  166.         sc_rover = sc_rover->next;
  167.         if (!sc_rover)
  168.             Sys_Error ("D_SCAlloc: hit the end of memory");
  169.         if (sc_rover->owner)
  170.             *sc_rover->owner = NULL;
  171.             
  172.         new->size += sc_rover->size;
  173.         new->next = sc_rover->next;
  174.     }
  175.  
  176. // create a fragment out of any leftovers
  177.     if (new->size - size > 256)
  178.     {
  179.         sc_rover = (surfcache_t *)( (byte *)new + size);
  180.         sc_rover->size = new->size - size;
  181.         sc_rover->next = new->next;
  182.         sc_rover->width = 0;
  183.         sc_rover->owner = NULL;
  184.         new->next = sc_rover;
  185.         new->size = size;
  186.     }
  187.     else
  188.         sc_rover = new->next;
  189.     
  190.     new->width = width;
  191. // DEBUG
  192.     if (width > 0)
  193.         new->height = (size - sizeof(*new) + sizeof(new->data)) / width;
  194.  
  195.     new->owner = NULL;              // should be set properly after return
  196.  
  197.     if (d_roverwrapped)
  198.     {
  199.         if (wrapped_this_time || (sc_rover >= d_initial_rover))
  200.             r_cache_thrash = true;
  201.     }
  202.     else if (wrapped_this_time)
  203.     {       
  204.         d_roverwrapped = true;
  205.     }
  206.  
  207. D_CheckCacheGuard ();   // DEBUG
  208.     return new;
  209. }
  210.  
  211.  
  212. /*
  213. =================
  214. D_SCDump
  215. =================
  216. */
  217. void D_SCDump (void)
  218. {
  219.     surfcache_t             *test;
  220.  
  221.     for (test = sc_base ; test ; test = test->next)
  222.     {
  223.         if (test == sc_rover)
  224.             Sys_Printf ("ROVER:\n");
  225.         printf ("%p : %i bytes     %i width\n",test, test->size, test->width);
  226.     }
  227. }
  228.  
  229. //=============================================================================
  230.  
  231. // if the num is not a power of 2, assume it will not repeat
  232.  
  233. int     MaskForNum (int num)
  234. {
  235.     if (num==128)
  236.         return 127;
  237.     if (num==64)
  238.         return 63;
  239.     if (num==32)
  240.         return 31;
  241.     if (num==16)
  242.         return 15;
  243.     return 255;
  244. }
  245.  
  246. int D_log2 (int num)
  247. {
  248.     int     c;
  249.     
  250.     c = 0;
  251.     
  252.     while (num>>=1)
  253.         c++;
  254.     return c;
  255. }
  256.  
  257. //=============================================================================
  258.  
  259. /*
  260. ================
  261. D_CacheSurface
  262. ================
  263. */
  264. surfcache_t *D_CacheSurface (msurface_t *surface, int miplevel)
  265. {
  266.     surfcache_t     *cache;
  267.     float           surfscale;
  268.  
  269. //
  270. // if the surface is animating or flashing, flush the cache
  271. //
  272.     r_drawsurf.texture = R_TextureAnimation (surface->texinfo->texture);
  273.     r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
  274.     r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
  275.     r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
  276.     r_drawsurf.lightadj[3] = d_lightstylevalue[surface->styles[3]];
  277.     
  278. //
  279. // see if the cache holds apropriate data
  280. //
  281.     cache = surface->cachespots[miplevel];
  282.  
  283.     if (cache && !cache->dlight && surface->dlightframe != r_framecount
  284.             && cache->texture == r_drawsurf.texture
  285.             && cache->lightadj[0] == r_drawsurf.lightadj[0]
  286.             && cache->lightadj[1] == r_drawsurf.lightadj[1]
  287.             && cache->lightadj[2] == r_drawsurf.lightadj[2]
  288.             && cache->lightadj[3] == r_drawsurf.lightadj[3] )
  289.         return cache;
  290.  
  291. //
  292. // determine shape of surface
  293. //
  294.     surfscale = 1.0 / (1<<miplevel);
  295.     r_drawsurf.surfmip = miplevel;
  296.     r_drawsurf.surfwidth = surface->extents[0] >> miplevel;
  297.     r_drawsurf.rowbytes = r_drawsurf.surfwidth;
  298.     r_drawsurf.surfheight = surface->extents[1] >> miplevel;
  299.     
  300. //
  301. // allocate memory if needed
  302. //
  303.     if (!cache)     // if a texture just animated, don't reallocate it
  304.     {
  305.         cache = D_SCAlloc (r_drawsurf.surfwidth,
  306.                            r_drawsurf.surfwidth * r_drawsurf.surfheight);
  307.         surface->cachespots[miplevel] = cache;
  308.         cache->owner = &surface->cachespots[miplevel];
  309.         cache->mipscale = surfscale;
  310.     }
  311.     
  312.     if (surface->dlightframe == r_framecount)
  313.         cache->dlight = 1;
  314.     else
  315.         cache->dlight = 0;
  316.  
  317.     r_drawsurf.surfdat = (pixel_t *)cache->data;
  318.     
  319.     cache->texture = r_drawsurf.texture;
  320.     cache->lightadj[0] = r_drawsurf.lightadj[0];
  321.     cache->lightadj[1] = r_drawsurf.lightadj[1];
  322.     cache->lightadj[2] = r_drawsurf.lightadj[2];
  323.     cache->lightadj[3] = r_drawsurf.lightadj[3];
  324.  
  325. //
  326. // draw and light the surface texture
  327. //
  328.     r_drawsurf.surf = surface;
  329.  
  330.     c_surf++;
  331.     R_DrawSurface ();
  332.  
  333.     return surface->cachespots[miplevel];
  334. }
  335.  
  336.  
  337.